package xgen;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import xdb.util.DatabaseMetaData;

import java.io.PrintStream;

public class Variable {
    private int jsonname;
    private final String name;
    private String type;
    private String key;
    private String value;
    private final String initial;
    private String comment;
    private String comparator;
    private String capacity;

    private final String Name;
    ///////////////////////////////////////////////////////////////////
    private Type vartype;
    private MODIFY_TYPES modifytype = MODIFY_TYPES.NONE;

    // 内部辅助
    Variable(String name) {
        this.name = name;
        this.Name = Main.toUpper1(name);
        this.comment = "";
        this.initial = "";
    }

    public Variable(Element self) {
        name = self.getAttribute("name").trim().toLowerCase();
        Main.verifyName(name);
        jsonname = Integer.valueOf(self.getAttribute("jsonname").trim());
        if (jsonname == 0) {
            throw new IllegalArgumentException("Not Find jsonname " + "@" + name);
        }
        type = self.getAttribute("type").trim();
        key = self.getAttribute("key").trim();
        value = self.getAttribute("value").trim();
        initial = self.getAttribute("default").trim();
        comparator = self.getAttribute("comparator");
        capacity = self.getAttribute("capacity");

        Node c = self.getNextSibling();
        if (c != null && Node.TEXT_NODE == c.getNodeType()) {
            comment = c.getTextContent().trim().replaceAll("[\r\n]", "");
        }

        Name = Main.toUpper1(name);
    }

    Variable(DatabaseMetaData.Bean.Variable bv) {
        jsonname = bv.getJsonName();
        name = bv.getName();
        Main.verifyName(name);
        type = bv.getTypeName();
        key = bv.getKeyTypeName();
        value = bv.getValueTypeName();
        if (value.isEmpty()) {
            value = "";
        }
        initial = "";
        capacity = "1024";
        comparator = "";

        Name = Main.toUpper1(name);
        //vartype = Type.compile(type, key, value);
        //vartype = bv.getTypeType();
    }

    public String getComparator() {
        return comparator;
    }

    public String getComment() {
        return comment;
    }

    public String getInitial() {
        return initial;
    }

    public String getName() {
        return Name;
    }

    public int getjsonname() {
        return jsonname;
    }

    public String getname() {
        return name;
    }

    public Type getVartype() {
        return vartype;
    }

    public void compile(Xdb xdb) {
        vartype = Type.compile(type, key, value);
    }

    public void verify(Xdb xdb, Type bean) {
        // verify capacity
        vartype.verifyCapacity(xdb, new Capacity(capacity, "bean." + bean.getName() + "." + getname()));

        if (bean.getName().equals("fxbean0") && this.name.equals("a")) {
            System.out.println();
        }
    }

    public void declare(PrintStream ps, String prefix) {
        ps.println(prefix + "private " + vartype.getTypeName() + " " + name + ";" + " // " + comment);
    }

    public void construct(XBean bean, PrintStream ps, String prefix) {
        vartype.construct(bean, this, ps, prefix);
    }

    public String defaultCheck() {
        return vartype.defaultCheck(this);
    }

    public void deepCopy(XBean bean, PrintStream ps, String prefix) {
        vartype.deepCopy(bean.isData(), this, ps, prefix);
    }

    public void marshal(XBean bean, PrintStream ps, String prefix) {
        vartype.marshal(bean, this, ps, prefix, this.getname());
    }

    public void unmarshal(XBean bean, PrintStream ps, String prefix) {
        vartype.unmarshal(bean, this, ps, prefix, this.getname());
    }

    public void marshalJson(XBean bean, PrintStream ps, String prefix, String localvarname) {
        vartype.marshalJson(bean, this, ps, prefix, localvarname + "." + this.getname());
    }

    public void unmarshalJson(XBean bean, PrintStream ps, String prefix, String localvarname) {
        vartype.unmarshalJson(bean, this, ps, prefix, localvarname + "." + this.getname());
    }

    public void setterInterface(XBean bean, PrintStream ps, String prefix) {
        vartype.setterInterface(bean, this, ps, prefix);
    }

    public void setterConst(XBean bean, PrintStream ps, String prefix) {
        vartype.setterConst(bean, this, ps, prefix);
    }

    public void setter(XBean bean, PrintStream ps, String prefix) {
        vartype.setter(bean, this, ps, prefix);
    }

    public void setterData(XBean bean, PrintStream ps, String prefix) {
        vartype.setterData(bean, this, ps, prefix);
    }

    public void getterInterface(XBean bean, PrintStream ps, String prefix) {
        vartype.getterInterface(bean, this, ps, prefix);
    }

    public void getterConst(XBean bean, PrintStream ps, String prefix) {
        vartype.getterConst(bean, this, ps, prefix);
    }

    public void getter(XBean bean, PrintStream ps, String prefix) {
        vartype.getter(bean, this, ps, prefix);
    }

    public void getterData(XBean bean, PrintStream ps, String prefix) {
        vartype.getterData(bean, this, ps, prefix);
    }

    public void equals(PrintStream ps, String prefix) {
        ps.println(prefix + "if (" + vartype.notEquals(name) + ") {");
        ps.println(prefix + "	return false;");
        ps.println(prefix + "}");
    }

    public void hashCode(PrintStream ps, String prefix) {
        ps.println(prefix + "_h_ += " + vartype.hashCode(name) + ";");
    }

    public void toString(PrintStream ps, String prefix) {
        vartype.toString(ps, prefix, name);
    }

    public String newListenable(XBean bean) {
        return vartype.newListenable(bean, this);
    }

    public boolean isAny() {
        return vartype.isAny();
    }

    public void printSelect(PrintStream ps, String K, String V) {
        if (vartype.isAny()) {
            return;
        }
        // xbean 类型为Cloneable类型生成select，当只需要一个字段时，提高效率。
        String F = vartype.getBoxingName();
        ps.println("	public static " + F + " select" + getName() + "(" + K + " key) throws Exception {");
        ps.println("		return getTable().select(key, new xdb.TField<" + V + ", " + F + ">() {");
        ps.println("				public " + F + " get(" + V + " v) {");
        ps.print("					return v.get" + getName());
        if (vartype instanceof TypeCollection || vartype instanceof TypeBaseMap) {
            ps.print("AsData");
        } else if (vartype instanceof TypeBinary) {
            ps.print("Copy");
        }
        ps.println("();");
        ps.println("				}");
        ps.println("			});");
        ps.println("	}");
        ps.println();

    }

    public String compareto() {
        return vartype.compareto(name, "_o_." + name);

    }

    public void printMetaData(PrintStream ps, String prefix) {
        ps.print(prefix + ", " + jsonname + ", " + Main.quote(name));
        ps.print(prefix + ", " + Main.quote(type) + ", " + Main.quote(key) + ", " + Main.quote(value) + ", " + Main.quote(comparator));
        ps.print(prefix + ", " + Main.quote(initial) + ", " + Main.quote(capacity));
    }

    public MODIFY_TYPES getModifyType() {
        return this.modifytype;
    }

    public void setModifyType(MODIFY_TYPES type) {
        this.modifytype = type;
    }

    public String getKeyTypeName() {
        return this.key;
    }

    public String getValueTypeName() {
        return this.value;
    }

    ///////--------增加对Transform的支持. caijiacheng 2009-9-1
    public enum MODIFY_TYPES {
        ADD, REMOVE, NONE
    }

}
